const { kvEvent, EVENT } = require('./lib/event');
const { kvModel } = require('./lib/mongo');

require('./alert/robot');

/**
 * 将数组转换为对象，加快查询速度
 * @param {import('./typings/consul').ConsulKv[]} list 
 */
function list2Map(list) {
  /** @type {{ [key: string]: import('./typings/consul').ConsulKv }} */
  const map = {};
  for (const item of list) {
    map[item.key] = item;
  }
  return map;
}

/**
 * @param {string} dc 机房名称
 * @param {import('./typings/consul').ConsulKv[]} list 从consul中读取到的所有kv
 */
async function diffDb(dc, list) {
  const consulMap = list2Map(list);
  const dbMap = list2Map(await kvModel.find({ dc }).lean());
  const keySet = new Set([...Object.keys(consulMap), ...Object.keys(dbMap)]);
  const warnList = [];
  for (const key of keySet) {
    const consulKv = consulMap[key];
    const dbKv = dbMap[key];
    if (!consulKv || !dbKv) {
      // consul中删除或新增了key未同步到数据库中
      warnList.push({
        type: EVENT.NO_SYNC,
        key,
        consulValue: consulKv?.value,
        dbValue: dbKv?.value,
        user: dbKv?.updateUser,
      });
      continue;
    }
    if (consulKv.modifyIndex !== dbKv.modifyIndex) {
      // 值发生变化
      warnList.push({
        type: EVENT.DIFF_VALUE,
        key,
        consulValue: consulKv.value,
        dbValue: dbKv.value,
        user: dbKv?.updateUser,
      });
      continue;
    }
  }
  for (const warn of warnList) {
    kvEvent.emit(warn.type, warn);
  }
}

/**
 * 
 * @param {import('./lib/consul').Consul} consul 
 * @returns 
 */
exports.watch = async function (consul) {
  const [err, dcList] = await consul.getDcList();
  if (err) {
    return;
  }
  for (const dc of dcList) {
    const [err, list] = await consul.getAllKv(dc, 0, '/online-school');
    if (err) {
      continue;
    }
    await diffDb(dc, list);
    for (const item of list) {
      consul.watchKey(dc, item.key, () => {
        return false;
      });
    }
  }
};
